/*********************************************************************************************************
* 模块名称：DAC.c
* 摘    要：DAC模块
* 当前版本：1.0.0
* 作    者：
* 完成日期：2025年02月06日 
* 内    容：
* 注    意：
**********************************************************************************************************
* 取代版本：
* 作    者：
* 完成日期：
* 修改内容:
* 修改文件：
*********************************************************************************************************/

/*********************************************************************************************************
*                                              包含头文件
*********************************************************************************************************/
#include "DAC.h"
#include "gd32f30x_conf.h"

/*********************************************************************************************************
*                                              宏定义
*********************************************************************************************************/
#define DAC0_R12DH_ADDR ((unsigned int)0x40007408)   //DAC0地址 （12位右对齐）
/*********************************************************************************************************
*                                              枚举结构体
*********************************************************************************************************/

/*********************************************************************************************************
*                                              内部变量定义
*********************************************************************************************************/
static uint16_t waveBuf[1000];
/*********************************************************************************************************
*                                              内部函数声明
*********************************************************************************************************/
static void ConfigTimer6(unsigned short arr, unsigned short psc);   //配置TIMER6
static void ConfigDAC0(void);                                       //配置DAC0
static void ConfigDMA1CH2ForDAC0(unsigned int bufAddr);             //配置DMA1通道2
/*********************************************************************************************************
*                                              内部函数实现
*********************************************************************************************************/

/*********************************************************************************************************
* 函数名称：ConfigDAC0
* 函数功能：配置DAC0
* 输入参数：void
* 输出参数：void
* 返 回 值：void
* 创建日期：2021年07月01日
* 注    意：
*********************************************************************************************************/
static void ConfigTimer6(unsigned short arr, unsigned short psc)
{
    timer_parameter_struct timer_initpara;                  //timer_initpara用于存放定时器参数
    
    rcu_periph_clock_enable(RCU_TIMER6);                    //使能TIMER6的时钟
    
    timer_deinit(TIMER6);                                   //设置TIMER6参数恢复默认值
    timer_struct_para_init(&timer_initpara);                //初始化timer_initpara
    
    //配置TIMER6
    timer_initpara.prescaler        = psc;                      //设置预分频值
    timer_initpara.counterdirection = TIMER_COUNTER_CENTER_UP;  //设置递增计数模式
    timer_initpara.period           = arr;                      //设置自动重装载值
    timer_initpara.clockdivision    = TIMER_CKDIV_DIV1;         //设置时钟分割
    timer_init(TIMER6, &timer_initpara);
    
    //TIMER6触发源配置
    timer_master_output_trigger_source_select(TIMER6, TIMER_TRI_OUT_SRC_UPDATE);
    
    timer_enable(TIMER6);
}

static void ConfigDAC0(void)
{
    //使用RUC相关时钟
    rcu_periph_clock_enable(RCU_GPIOA); //使用GPIOA时钟
    rcu_periph_clock_enable(RCU_DAC);   //使用DAC时钟
    
    //设置GPIO输出模式及速率
    gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
    
    //DAC0配置
    dac_deinit();                                           //复位DAC模块
    dac_concurrent_disable();                               //禁用concurrent（并发） mode
    dac_output_buffer_enable(DAC0);                         //使用输出缓冲区
    dac_trigger_enable(DAC0);                               //使用外部触发源
    dac_trigger_source_config(DAC0, DAC_TRIGGER_T6_TRGO);   //使用TIMER6作为触发源
    dac_wave_mode_config(DAC0, DAC_WAVE_DISABLE);           //禁用Wave mode
            
    //使能DAC0的DMA
    dac_dma_enable(DAC0);
    
    //使能DAC0
    dac_enable(DAC0);
}

static void ConfigDMA1CH2ForDAC0(unsigned int bufAddr)
{
    //DMA配置结构体
    dma_parameter_struct dma_struct;
    
    //使能DMA1时钟
    rcu_periph_clock_enable(RCU_DMA1);
    
    //配置DMA1_CH2
    dma_deinit(DMA1, DMA_CH2);                                  //复位DMA
    dma_struct_para_init(&dma_struct);                          //复位配置结构体
    dma_struct.periph_addr = DAC0_R12DH_ADDR;                   //外设地址
    dma_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;       //外设数据位宽为16位
    dma_struct.memory_addr = bufAddr;                           //内存地址
    dma_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;           //内存数据宽度为16位
    dma_struct.number = 1000;                                   //传输数据量
    dma_struct.priority = DMA_PRIORITY_HIGH;                    //高优先级
    dma_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;        //外设地址增长关闭
    dma_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;         //内存地址正常开启
    dma_struct.direction = DMA_MEMORY_TO_PERIPHERAL;            //传输方向为内存到外设
    dma_init(DMA1, DMA_CH2, &dma_struct);                       //根据参数配置DMA1_CH2
    dma_circulation_enable(DMA1, DMA_CH2);                      //开启循环模式
                                                                
    nvic_irq_enable(DMA1_Channel2_IRQn, 0, 0);                  //中断线配置
    dma_interrupt_enable(DMA1, DMA_CH2, DMA_INT_FTF);           //使能DMA中断                       z
    
    //使能DMA1_CH2
    dma_channel_enable(DMA1, DMA_CH2);
}

/*********************************************************************************************************
*                                              API函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称：InitDAC
* 函数功能：初始化DAC模块
* 输入参数：void
* 输出参数：void
* 返 回 值：void
* 创建日期：2025年01月06日
* 注    意：
*********************************************************************************************************/
void InitDAC(void)
{
    for(int i = 0; i < 500; i++){
        waveBuf[i] = (i+524) * 4;
    }
    for(int i = 500; i < 1000; i++){
        waveBuf[i] = 4 * (1524 - i);
    }
    ConfigTimer6(7999,119);
    ConfigDAC0();
    ConfigDMA1CH2ForDAC0((uint32_t)waveBuf);
}

void DMA1_Channel2_IRQHandler(void)
{
    if(RESET != dma_interrupt_flag_get(DMA1, DMA_CH2, DMA_INT_FLAG_FTF)){
        
        __NVIC_ClearPendingIRQ(DMA1_Channel1_IRQn);
        
        dma_interrupt_flag_clear(DMA1, DMA_CH2, DMA_INT_FLAG_FTF);
        
        ConfigDMA1CH2ForDAC0((uint32_t)waveBuf);
    }
}

